

package com.dog.basics.service.sys.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.Validator;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.dog.basics.bean.dto.admin.sys.*;
import com.dog.basics.bean.model.sys.*;
import com.dog.basics.bean.vo.admin.common.AdminComFileInfosVo;
import com.dog.basics.bean.vo.admin.sys.*;
import com.dog.basics.common.constant.CacheConstants;
import com.dog.basics.common.constant.ComFileInfoConstant;
import com.dog.basics.common.constant.CommonConstants;
import com.dog.basics.common.util.PageParam;
import com.dog.basics.dao.sys.SysUserInfoMapper;
import com.dog.basics.dao.sys.SysUserMapper;
import com.dog.basics.service.common.IDogComFileInfoService;
import com.dog.basics.service.sys.*;
import io.micrometer.core.instrument.util.StringUtils;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import ma.glasnost.orika.MapperFacade;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * @author guonh
 * @date 2017/10/31
 */
@Slf4j
@Service
@AllArgsConstructor
public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> implements SysUserService {
    private final PasswordEncoder passwordEncoder;
    private final SysMenuService sysMenuService;
    private final SysUserInfoMapper userInfoMapper;
    private final SysRoleService sysRoleService;

    private final SysDeptService sysDeptService;

    private final SysUserRoleService sysUserRoleService;
    private final MapperFacade mapperFacade;
    private final SysDeptRelationService sysDeptRelationService;

    private final IDogComFileInfoService dogComFileInfoService;

    /**
     * 根据用户id获取用户信息
     *
     * @param userName
     * @return
     */

    @Override
    public SysUserPageVo getSysUserByUserName(String userName) {
        SysUserPageVo newsVo = new SysUserPageVo();
        List<SysUser> list = this.list(Wrappers.<SysUser>lambdaQuery().eq(SysUser::getUsername, userName));
        if (CollUtil.isNotEmpty(list)) {
            BeanUtil.copyProperties(list.get(0), newsVo);
            newsVo.setStatus(list.get(0).getLockFlag());
            return newsVo;
        } else {
            return null;

        }
    }

    /**
     * 保存用户信息
     *
     * @param obj DTO 对象
     * @return success/fail
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean saveUser(AdminSysUserAddDto obj) {
        // 数据信息转化
        SysUser sysUser = BeanUtil.toBean(obj, SysUser.class);
        sysUser.setDelFlag(CommonConstants.STATUS_NORMAL);
        sysUser.setPassword(passwordEncoder.encode(obj.getPassword()));
        sysUser.setCreateTime(DateUtil.currentSeconds());
        Validator.validateTrue(this.save(sysUser), "添加用户失败");
        // 添加角色信息
        List<SysUserRole> userRoleList = obj.getRole().stream().map(roleId -> {
            SysUserRole userRole = new SysUserRole();
            userRole.setUserId(sysUser.getUserId());
            userRole.setRoleId(roleId);
            return userRole;
        }).collect(Collectors.toList());
        sysUserRoleService.saveBatch(userRoleList);
        // 添加基础信息
        SysUserInfo userInfo = new SysUserInfo();
        if (ObjectUtil.isNotNull(obj.getUserInfoDto())) {
            BeanUtil.copyProperties(obj.getUserInfoDto(), userInfo);
        }
        userInfo.setRealName(obj.getName());
        userInfo.setUserId(sysUser.getUserId());
        userInfo.insert();
        return Boolean.TRUE;
    }

    /**
     * @Description: 启用冻结用户
     * @Param: Boolean
     * @return: Boolean
     * @Author: wph
     * @Date: 2020/4/9  0027
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean nouse(Long id) {
        SysUser user = this.getById(id);
        Validator.validateNotNull(user, "common.noData");
        user.setLockFlag(user.getLockFlag() == 0 ? 9 : 0);
        Validator.validateTrue(this.updateById(user), "common.edit");
        return Boolean.TRUE;
    }

    /**
     * @Description: 是否强制用户修改密码
     * @Param: Boolean
     * @return: Boolean
     * @Author: wph
     * @Date: 2020/4/9  0027
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean sfPassword(Long id) {
        SysUser user = this.getById(id);
        Validator.validateNotNull(user, "common.noData");
        user.setSfPassword(0);
        Validator.validateTrue(this.updateById(user), "common.edit");
        return Boolean.TRUE;
    }

    /**
     * 重置密码
     *
     * @param obj
     * @return guonh 2020年2月10日
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean editResetPassword(AdminSysUserResetDto obj) {
        // 查询用户信息是否存在
        SysUser sysUser = this.getById(obj.getUserId());
        Validator.validateNotNull(sysUser, "common.noData");
        // 执行重置密码
        SysUser editSysUser = new SysUser();
        editSysUser.setUserId(sysUser.getUserId());
        editSysUser.setPassword(passwordEncoder.encode(obj.getPassword()));
        editSysUser.setSfPassword(1);
        Validator.validateTrue(this.updateById(editSysUser), "common.edit");
        return Boolean.TRUE;

    }

    /**
     * 通过查用户的全部信息
     *
     * @param id 用户
     * @return
     */
    @Override
    public AdminUserVo findUserInfo(Long id) {
        SysUser sysUser = this.getById(id);
        Validator.validateNotNull(sysUser, "common.noData");
        AdminUserVo userInfo = BeanUtil.toBean(sysUser, AdminUserVo.class);
        // 设置角色列表 （ID）
        List<Long> roleIds = sysRoleService.findRolesByUserId(sysUser.getUserId()).stream().map(AdminSysRoleVo::getRoleId)
                .collect(Collectors.toList());
        userInfo.setRoles(ArrayUtil.toArray(roleIds, Long.class));
        // 设置权限列表（menu.permission）
        if (Validator.equal(id, 1L)) {

            // 设置权限列表（menu.permission）
            Set<String> permissions = new HashSet<>();
            permissions.addAll(sysMenuService.list(Wrappers.<SysMenu>lambdaQuery()).stream().map(e -> e.getPermission()).collect(Collectors.toList()));
            userInfo.setPermissions(ArrayUtil.toArray(permissions, String.class));
        } else {
            // 设置权限列表（menu.permission）
            Set<String> permissions = new HashSet<>();
            roleIds.forEach(roleId -> {
                List<String> permissionList = sysMenuService.findMenuByRoleId(roleId).stream()
                        .filter(menuVo -> StringUtils.isNotEmpty(menuVo.getPermission())).map(AdminMenuVO::getPermission)
                        .collect(Collectors.toList());
                permissions.addAll(permissionList);
            });
            userInfo.setPermissions(ArrayUtil.toArray(permissions, String.class));
        }
        List<AdminComFileInfosVo> fileInfos = dogComFileInfoService.getAdminComFileInfos(id, ComFileInfoConstant.SYSUSER);
        if (CollUtil.isNotEmpty(fileInfos)) {
            userInfo.setAdminComFileInfosVo(fileInfos.get(0));
        }

        return userInfo;
    }

    /**
     * 分页查询用户信息（含有角色信息）
     *
     * @param page 分页对象
     * @param obj  参数列表
     * @return
     */
    @Override
    public IPage<AdminUserInfoVo> getUsersWithRolePage(PageParam page, AdminSysUserFromDto obj) {
        this.page(page, Wrappers.<SysUser>lambdaQuery()
                .eq(ObjectUtil.isNotNull(obj.getDeptId()), SysUser::getDeptId, obj.getDeptId())
                .like(StrUtil.isNotBlank(obj.getName()), SysUser::getName, obj.getName())
                .like(StrUtil.isNotBlank(obj.getUsername()), SysUser::getUsername, obj.getUsername())
                .like(StrUtil.isNotBlank(obj.getPhone()), SysUser::getPhone, obj.getPhone())
                .orderBy(Boolean.TRUE, obj.getIsOrderByAvg(), SysUser::getCreateTime));
        List<SysUser> records = page.getRecords();
        page.setRecords(records.stream().map(e -> {
            AdminUserInfoVo newVo = BeanUtil.toBean(e, AdminUserInfoVo.class);
            SysDept sysDept = sysDeptService.getById(e.getDeptId());
            newVo.setDeptName(ObjectUtil.isNotNull(sysDept) ? sysDept.getName() : "");
            List<Long> roleIdList = sysUserRoleService.list(Wrappers.<SysUserRole>lambdaQuery().eq(SysUserRole::getUserId, e.getUserId())).stream().map(f -> f.getRoleId()).collect(Collectors.toList());
            if (CollUtil.isNotEmpty(roleIdList)) {
                List<SysRole> list = sysRoleService.list(Wrappers.<SysRole>lambdaQuery().in(SysRole::getRoleId, roleIdList));
                List<AdminSysRoleVo> roleList = mapperFacade.mapAsList(list, AdminSysRoleVo.class);
                newVo.setRoleList(roleList);
            }
            List<AdminComFileInfosVo> fileInfos = dogComFileInfoService.getAdminComFileInfos(e.getUserId(), ComFileInfoConstant.SYSUSER);
            newVo.setAdminComFileInfosVo(fileInfos);
            //  查询基本信息
            SysUserInfo userInfo = userInfoMapper.selectById(e.getUserId());
            newVo.setUserInfoVo(ObjectUtil.isNotNull(userInfo) ? BeanUtil.toBean(userInfo, AdminSysUserInfoVo.class) : new AdminSysUserInfoVo());

            return newVo;
        }).collect(Collectors.toList()));
        return page;
    }

    @Override
    public IPage<AdminUserInfoVo> getUsersWithRoleCodePage(PageParam page, AdminSysUserFromDto obj) {
        IPage<AdminUserInfoVo> roleCodePage = this.baseMapper.getUsersWithRoleCodePage(page, obj);
        for (int i = 0; i < roleCodePage.getRecords().size(); i++) {
            //  查询基本信息
            SysUserInfo userInfo = userInfoMapper.selectById(roleCodePage.getRecords().get(i).getUserId());
            roleCodePage.getRecords().get(i).setUserInfoVo(ObjectUtil.isNotNull(userInfo) ? BeanUtil.toBean(userInfo, AdminSysUserInfoVo.class) : new AdminSysUserInfoVo());
        }
        return roleCodePage;
    }

    /**
     * 通过ID查询用户信息
     *
     * @param id 用户ID
     * @return 用户信息
     */
    @Override
    public AdminUserInfoVo selectUserVoById(Long id) {
        AdminUserInfoVo adminUserInfoVo = this.baseMapper.getUserVoById(id);
        List<AdminComFileInfosVo> fileInfos = dogComFileInfoService.getAdminComFileInfos(id, ComFileInfoConstant.SYSUSER);
        adminUserInfoVo.setAdminComFileInfosVo(fileInfos);
        return adminUserInfoVo;
    }

    /**
     * 通过ID查询用户信息
     *
     * @param id 用户ID
     * @return 用户信息
     */
    @Override
    public AdminUserXqVo getObjXq(Long id) {
        SysUser sysUser = this.getById(id);
        Validator.validateNotNull(sysUser, "common.noData");
        AdminUserXqVo newVo = new AdminUserXqVo();
        BeanUtil.copyProperties(sysUser, newVo);
        return newVo;
    }

    /**
     * 删除用户
     *
     * @param sysUser 用户
     * @return Boolean
     */
    @Override
    @CacheEvict(value = CacheConstants.USER_DETAILS, key = "#sysUser.username")
    public Boolean deleteUserById(SysUser sysUser) {
        sysUserRoleService.deleteByUserId(sysUser.getUserId());
        this.removeById(sysUser.getUserId());
        return Boolean.TRUE;
    }

    /**
     * 更新当前用户基本信息
     *
     * @param obj 用户信息
     * @return Boolean
     */
    @Override
    @CacheEvict(value = CacheConstants.USER_DETAILS, key = "#obj.username")
    public Boolean updateUserInfo(AdminSysUserEditInfoDto obj, SysUser sysUser) {

        if (StrUtil.isNotBlank(obj.getNewpassword1())) {
            Validator.validateTrue(passwordEncoder.matches(obj.getPassword(), sysUser.getPassword()), "The original password is incorrect");
            sysUser.setPassword(passwordEncoder.encode(obj.getNewpassword1()));
            sysUser.setSfPassword(1);
        }
        sysUser.setName(obj.getName());
        SysUserInfo userInfo = new SysUserInfo();
        userInfo.setRealName(obj.getName());
        userInfo.setUserId(sysUser.getUserId());
        userInfo.updateById();
        // 处理文件信息
        if (ObjectUtil.isNotNull(obj.getFileId())) {
            List<Long> fileIds = CollUtil.newArrayList(obj.getFileId());
            // 处理文件信息
            Boolean fileSuccess = dogComFileInfoService.editDelUsedAddNotUsed(fileIds, sysUser.getUserId(), ComFileInfoConstant.SYSUSER);
            Validator.validateTrue(fileSuccess, "file.error");
        } else {
            List<Long> fileIds = CollUtil.newArrayList();
            // 处理文件信息
            Boolean fileSuccess = dogComFileInfoService.editDelUsedAddNotUsed(fileIds, sysUser.getUserId(), ComFileInfoConstant.SYSUSER);
            Validator.validateTrue(fileSuccess, "file.error");
        }
        Validator.validateTrue(this.updateById(sysUser), "common.edit");
        return Boolean.TRUE;
    }

    /**
     * 更新指定用户信息
     *
     * @param obj 用户信息
     * @return
     */
    @Override
    @CacheEvict(value = CacheConstants.USER_DETAILS, key = "#obj.username")
    public Boolean updateUser(AdminSysUserEditDto obj) {
        // 查询用户信息是否存在
        SysUser sysUser = this.getById(obj.getUserId());
        Validator.validateNotNull(sysUser, "common.noData");
        // 数据信息转换
        SysUser eidtSysUser = BeanUtil.toBean(obj, SysUser.class);
        eidtSysUser.setUpdateTime(DateUtil.currentSeconds());
        if (StrUtil.isNotBlank(obj.getPassword())) {
            eidtSysUser.setPassword(passwordEncoder.encode(obj.getPassword()));
        }
        // 修改用户信息
        Validator.validateTrue(eidtSysUser.updateById(), "common.edit");
        // 先删除角色信息
        sysUserRoleService.remove(Wrappers.<SysUserRole>update().lambda().eq(SysUserRole::getUserId, obj.getUserId()));
        // 执行修改添加操作
        obj.getRole().forEach(roleId -> {
            SysUserRole userRole = new SysUserRole();
            userRole.setUserId(sysUser.getUserId());
            userRole.setRoleId(roleId);
            userRole.insert();
        });
        // 修改基础信息
        SysUserInfo userInfo = new SysUserInfo();
        if (ObjectUtil.isNotNull(obj.getUserInfoDto())) {
            BeanUtil.copyProperties(obj.getUserInfoDto(), userInfo);
        }
        userInfo.setRealName(obj.getName());
        userInfo.setUserId(sysUser.getUserId());
        userInfo.updateById();
        return Boolean.TRUE;
    }

    /**
     * 查询上级部门的用户信息
     *
     * @param username 用户名
     * @return R
     */
    @Override
    public List<AdminUserInfoVo> listAncestorUsers(String username) {
        List<SysUser> userLit = this.list(Wrappers.<SysUser>query().lambda().eq(SysUser::getUsername, username));
        Validator.validateTrue(CollUtil.isNotEmpty(userLit), "common.noData!");
        SysUser sysUser = userLit.get(0);
        SysDept sysDept = sysDeptService.getById(sysUser.getDeptId());
        Validator.validateNotNull(sysDept, "common.noData!");
        Long parentId = sysDept.getParentId();
        List<SysUser> list = this.list(Wrappers.<SysUser>query().lambda().eq(SysUser::getDeptId, parentId));
        List<AdminUserInfoVo> newList = mapperFacade.mapAsList(list, AdminUserInfoVo.class);
        newList.forEach(e -> {
            SysDept sysDept1 = sysDeptService.getById(e.getDeptId());
            e.setDeptName(ObjectUtil.isNotNull(sysDept1) ? sysDept1.getName() : "");
            List<Long> roleIdList = sysUserRoleService.list(Wrappers.<SysUserRole>lambdaQuery().eq(SysUserRole::getUserId, e.getUserId())).stream().map(f -> f.getRoleId()).collect(Collectors.toList());
            if (CollUtil.isNotEmpty(roleIdList)) {
                List<SysRole> list1 = sysRoleService.list(Wrappers.<SysRole>lambdaQuery().in(SysRole::getRoleId, roleIdList));
                List<AdminSysRoleVo> roleList = mapperFacade.mapAsList(list1, AdminSysRoleVo.class);
                e.setRoleList(roleList);
            }
        });
        return newList;
    }

    /**
     * 获取当前用户的子部门信息
     *
     * @return 子部门列表
     */
/*    private List<Long> getChildDepts() {
        Long deptId = SecurityUtils.getUser().getDeptId();
        // 获取当前部门的子部门
        return sysDeptRelationService
                .list(Wrappers.<SysDeptRelation>query().lambda().eq(SysDeptRelation::getAncestor, deptId)).stream()
                .map(SysDeptRelation::getDescendant).collect(Collectors.toList());
    }*/

}
